#ifndef __UTILS_H__
#define __UTILS_H__

#pragma once
#include "debug_macro.h"
namespace DuiLib
{
    /////////////////////////////////////////////////////////////////////////////////////
    //

    class DUILIB_API STRINGorID
    {
    public:
        STRINGorID(LPCTSTR lpString);
        STRINGorID(unsigned int nID);

        LPCTSTR m_lpstr;
    };

    /////////////////////////////////////////////////////////////////////////////////////
    //
    class CDuiString;
    class DUILIB_API CDuiPoint : public tagPOINT
    {
    public:
        CDuiPoint();
        CDuiPoint(const POINT& src);
        CDuiPoint(long x, long y);
        CDuiPoint(LPARAM lParam);
        CDuiPoint(LPCTSTR pstrValue);
        CDuiString ToString();
    };

    /////////////////////////////////////////////////////////////////////////////////////
    //

    class DUILIB_API CDuiSize : public tagSIZE
    {
    public:
        CDuiSize();
        CDuiSize(const SIZE& src);
        CDuiSize(const RECT rc);
        CDuiSize(long cx, long cy);
        CDuiSize(LPCTSTR pstrValue);
        CDuiString ToString();
    };

    /////////////////////////////////////////////////////////////////////////////////////
    //

    class DUILIB_API CDuiRect : public tagRECT
    {
    public:
        CDuiRect();
        CDuiRect(const RECT& src);
        CDuiRect(long iLeft, long iTop, long iRight, long iBottom);
        CDuiRect(LPCTSTR pstrValue);
        CDuiString ToString();

        int GetWidth() const;
        int GetHeight() const;
        void Empty();
        bool IsNull() const;
        void Join(const RECT& rc);
        void ResetOffset();
        void Normalize();
        void Offset(int cx, int cy);
        void Inflate(int cx, int cy);
        void Deflate(int cx, int cy);
        void Union(CDuiRect& rc);
    };

    /////////////////////////////////////////////////////////////////////////////////////
    //

    class DUILIB_API CDuiString
    {
    public:
        enum
        {
            MAX_LOCAL_STRING_LEN = 63
        };

        CDuiString();
        CDuiString(const TCHAR ch);
        CDuiString(const CDuiString& src);
        CDuiString(LPCTSTR lpsz, int nLen = -1);
        ~CDuiString();
        CDuiString ToString();

        void Empty();
        int GetLength() const;
        int GetSize() const;
        bool IsEmpty() const;
        TCHAR GetAt(int nIndex) const;
        void Append(LPCTSTR pstr);
        void Assign(LPCTSTR pstr, int nLength = -1);
        LPCTSTR GetData() const;

        void SetAt(int nIndex, TCHAR ch);
        operator LPCTSTR() const;

        TCHAR operator[] (int nIndex) const;
        const CDuiString& operator=(const CDuiString& src);
        const CDuiString& operator=(const TCHAR ch);
        const CDuiString& operator=(LPCTSTR pstr);
#ifdef _UNICODE
        const CDuiString& operator=(LPCSTR lpStr);
        const CDuiString& operator+=(LPCSTR lpStr);
#else
        const CDuiString& operator=(LPCWSTR lpwStr);
        const CDuiString& operator+=(LPCWSTR lpwStr);
#endif
        CDuiString operator+(const CDuiString& src) const;
        CDuiString operator+(LPCTSTR pstr) const;
        const CDuiString& operator+=(const CDuiString& src);
        const CDuiString& operator+=(LPCTSTR pstr);
        const CDuiString& operator+=(const TCHAR ch);

        bool operator == (LPCTSTR str) const;
        bool operator != (LPCTSTR str) const;
        bool operator <= (LPCTSTR str) const;
        bool operator <  (LPCTSTR str) const;
        bool operator >= (LPCTSTR str) const;
        bool operator >  (LPCTSTR str) const;

        int Compare(LPCTSTR pstr) const;
        int CompareNoCase(LPCTSTR pstr) const;

        void MakeUpper();
        void MakeLower();

        CDuiString Left(int nLength) const;
        CDuiString Mid(int iPos, int nLength = -1) const;
        CDuiString Right(int nLength) const;

        int Find(TCHAR ch, int iPos = 0) const;
        int Find(LPCTSTR pstr, int iPos = 0) const;
        int ReverseFind(TCHAR ch) const;
        int Replace(LPCTSTR pstrFrom, LPCTSTR pstrTo);

        int __cdecl Format(LPCTSTR pstrFormat, ...);
        int __cdecl SmallFormat(LPCTSTR pstrFormat, ...);

    protected:
        LPTSTR m_pstr;
        TCHAR m_szBuffer[MAX_LOCAL_STRING_LEN + 1];
    };

    /////////////////////////////////////////////////////////////////////////////////////
    //

    class DUILIB_API CDuiPtrArray
    {
    public:
        CDuiPtrArray(int iPreallocSize = 0);
        CDuiPtrArray(const CDuiPtrArray& src);
        ~CDuiPtrArray();

        void Empty();
        void Resize(int iSize);
        bool IsEmpty() const;
        int Find(LPVOID iIndex) const;
        bool Add(LPVOID pData);
        bool SetAt(int iIndex, LPVOID pData);
        bool InsertAt(int iIndex, LPVOID pData);
        bool InsertRangesAt(int start_index, LPVOID* pData, int count);
        bool Remove(int iIndex, int iCount = 1);
        int GetSize() const;
        LPVOID* GetData();

        LPVOID GetAt(int iIndex) const;
        LPVOID operator[] (int nIndex) const;

#ifdef OUT_DEBUG_STRING
        void SetOwnerName(const TCHAR* pOwerName);
        TCHAR m_Temp[50]{ 0 };
#endif
    protected:
        LPVOID* m_ppVoid;
        int m_nCount;
        int m_nAllocated;
    };


    /////////////////////////////////////////////////////////////////////////////////////
    //

    class DUILIB_API CDuiValArray
    {
    public:
        CDuiValArray(int iElementSize, int iPreallocSize = 0);
        ~CDuiValArray();

        void Empty();
        bool IsEmpty() const;
        bool Add(LPCVOID pData);
        bool Remove(int iIndex, int iCount = 1);
        int GetSize() const;
        LPVOID GetData();

        LPVOID GetAt(int iIndex) const;
        LPVOID operator[] (int nIndex) const;

    protected:
        LPBYTE m_pVoid;
        int m_iElementSize;
        int m_nCount;
        int m_nAllocated;
    };

    /////////////////////////////////////////////////////////////////////////////////////
    //

    struct TITEM;
    class DUILIB_API CDuiStringPtrMap
    {
    public:
        CDuiStringPtrMap(int nSize = 83);
        ~CDuiStringPtrMap();

        void Resize(int nSize = 83);
        LPVOID Find(LPCTSTR key, bool optimize = true) const;
        bool Insert(LPCTSTR key, LPVOID pData);
        LPVOID Set(LPCTSTR key, LPVOID pData);
        bool Remove(LPCTSTR key);
        void RemoveAll();
        int GetSize() const;
        LPCTSTR GetAt(int iIndex) const;
        LPCTSTR operator[] (int nIndex) const;

        int bbb3 = 0;
    protected:
        TITEM** m_aT;
        int m_nBuckets;
        int m_nCount;
    };

    /////////////////////////////////////////////////////////////////////////////////////
    //

    class DUILIB_API CWaitCursor
    {
    public:
        CWaitCursor();
        ~CWaitCursor();

    protected:
        HCURSOR m_hOrigCursor;
    };

    /////////////////////////////////////////////////////////////////////////////////////
    //

    class CVariant : public VARIANT
    {
    public:
        CVariant()
        {
            VariantInit(this);
        }
        CVariant(int i)
        {
            VariantInit(this);
            this->vt = VT_I4;
            this->intVal = i;
        }
        CVariant(float f)
        {
            VariantInit(this);
            this->vt = VT_R4;
            this->fltVal = f;
        }
        CVariant(LPOLESTR s)
        {
            VariantInit(this);
            this->vt = VT_BSTR;
            this->bstrVal = s;
        }
        CVariant(IDispatch* disp)
        {
            VariantInit(this);
            this->vt = VT_DISPATCH;
            this->pdispVal = disp;
        }

        ~CVariant()
        {
            VariantClear(this);
        }
    };

}// namespace DuiLib

#endif // __UTILS_H__
